package com.tbit.main.controller;

import cn.hutool.core.collection.CollUtil;
import com.tbit.main.common.JsonResult;
import com.tbit.main.constant.MapConstant;
import com.tbit.main.constant.SysConstant;
import com.tbit.main.exception.BaseException;
import com.tbit.main.pojo.*;
import com.tbit.main.pojo.VO.WorkOrderFinishingCountRespVO;
import com.tbit.main.pojo.VO.WorkOrderFinishingQueryReqVO;
import com.tbit.main.pojo.VO.WorkOrderFinishingRespVO;
import com.tbit.main.service.*;
import com.tbit.main.util.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 工单车辆筛选
 *
 * @author LMY
 * @create 2021-05-25 10:52
 */
@RestController
@RequestMapping("/workOrderMachine")
public class WorkOrderMachineController {

    @Autowired
    private TokenService tokenService;
    @Autowired
    private WorkOrderMachineService workOrderMachineService;
    @Autowired
    private WorkOrderFinishingService workOrderFinishingService;
    @Autowired
    private MachineService machineService;
    @Autowired
    private MachineStatusService machineStatusService;
    @Autowired
    private CalibrateService calibrateService;
    @Autowired
    private DataService dataService;

    /**
     * 根据车辆编号查询
     *
     * @param token
     * @param userCode
     * @return
     */
    @RequestMapping("/getByUserCode")
    public JsonResult getByUserCode(String token, String userCode, Integer mapType) {
        Assert.hasLength(userCode, "Machine.userCode.notNull");

        AccountUser accountUserToken = tokenService.getAccount(token);

        /* 校验 */

        /**查询设备信息*/
        Machine machine = machineService.getByUseCode(userCode);

        if (machine == null) {
            throw new BaseException("Machine.notExist");
        }
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }


        /**设备权限判断*/
        machineService.auth(accountUserToken.getAgents(), machine.getMachineId());

        MachineStatus machineStatus = machineStatusService.getByMachineId(machine.getMachineId());

        /**校准经纬度*/
        if (machineStatus != null) {
            Point point = new Point(machineStatus.getLon(), machineStatus.getLat());
            calibrateService.commonCalibrate(point, MapConstant.MAP_ORI, mapType);
            machineStatus.setLonC(point.getX());
            machineStatus.setLatC(point.getY());

            /**用户码、中控码*/
            machineStatus.setUserCode(machine.getUserCode());
            machineStatus.setMachineNO(machine.getMachineNO());
        } else {
            throw new BaseException("Machine.notActive");
        }

        List<WorkOrderFinishing> workOrderFinishingList = workOrderFinishingService.getByMachineId(machine.getMachineId());
        Map<String, Object> map = new HashMap<>();
        map.put("machineStatus", machineStatus);
        if (workOrderFinishingList.size() > 0) {
            map.put("workOrderFinishing", workOrderFinishingList.get(0));
        }

        return JsonResult.succ(map);
    }

    /**
     * 根据电量查询
     */
    @RequestMapping("/getByPower")
    public JsonResult getByPower(String token, Integer accountId, Integer soc, Integer mapType) {
        AccountUser accountUserToken = tokenService.getAccount(token);
        Assert.notNull(accountId, "AccountUser.agentId.notNull");
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }

        if (soc == null) {
            soc = 30;
        }

        List<Map<String, Object>> machineStatuses = workOrderMachineService.getByPower(accountId, soc, mapType, accountUserToken);

        return JsonResult.succ(machineStatuses);
    }

    /**
     * 闲置车辆查询
     */
    @RequestMapping("/getByUnuse")
    public JsonResult getByUnuse(String token, Integer accountId, Integer hours, Integer mapType) {
        AccountUser accountUserToken = tokenService.getAccount(token);
        Assert.notNull(accountId, "AccountUser.agentId.notNull");
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }

        if (hours == null) {
            hours = 12;
        }


        List<Map<String, Object>> machineStatusBorrows = workOrderMachineService.getByUnuse(accountId, hours, mapType, accountUserToken);

        return JsonResult.succ(machineStatusBorrows);
    }

    /**
     * 异常车辆
     */
    @RequestMapping("/getByAbnormal")
    public JsonResult getByAbnormal(String token, Integer accountId, WorkOrderMachine workOrderMachine, Integer mapType) {
        AccountUser accountUserToken = tokenService.getAccount(token);
        Assert.notNull(accountId, "AccountUser.agentId.notNull");
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }

        List<Map<String, Object>> machineStatusAbnormales = workOrderMachineService.getByAbnormal(accountId, workOrderMachine.getAbnormalType(), mapType, accountUserToken);

        return JsonResult.succ(machineStatusAbnormales);
    }

    /**
     * 故障车辆
     */
    @RequestMapping("/getByFault")
    public JsonResult getByFault(String token, Integer accountId, Integer mapType, WorkOrderMachine workOrderMachine) {
        AccountUser accountUserToken = tokenService.getAccount(token);
        Assert.notNull(accountId, "AccountUser.agentId.notNull");
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }

        List<Map<String, Object>> machineStatusFaults = workOrderMachineService.getByFault(accountId, mapType, workOrderMachine.getAbnormalType(), accountUserToken);

        return JsonResult.succ(machineStatusFaults);
    }

    /**
     * 根据工单类型查询
     *
     * @param token
     * @param state
     * @return
     */
    @RequestMapping("/getByWorkFinish")
    public JsonResult getByWorkFinish(String token, Integer accountId, Integer state, Integer workType, Integer mapType) {

        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }

        AccountUser accountUser = tokenService.getAccount(token);
        Assert.notNull(workType, "WorkOrder.workType.notNull");
        List<WorkOrderFinishing> workOrderFinishingList = workOrderFinishingService.getByAccountIdUserId(accountId, accountUser, null, null, state, workType);

        if (CollUtil.isEmpty(workOrderFinishingList)) {
            return JsonResult.succ(workOrderFinishingList);
        }

        Map<Integer, Object> workOrderFinishMap = new HashMap<>();
        for (WorkOrderFinishing workOrderFinishing : workOrderFinishingList) {
            workOrderFinishMap.put(workOrderFinishing.getMachineId(), workOrderFinishing);
        }

        List<Integer> machineIds = workOrderFinishingList.stream().map(WorkOrderFinishing::getMachineId).collect(Collectors.toList());
        machineIds = machineIds.stream().filter(Objects::nonNull).collect(Collectors.toList());
        List<MachineStatus> machineStatuses = machineStatusService.getByMachineIdBatch(machineIds);

        List<Map<String, Object>> mapList = new ArrayList<>();
        for (MachineStatus machineStatus : machineStatuses) {
            /**校准经纬度*/
            if (machineStatus != null) {
                Point point = new Point(machineStatus.getLon(), machineStatus.getLat());
                calibrateService.commonCalibrate(point, MapConstant.MAP_ORI, mapType);
                machineStatus.setLonC(point.getX());
                machineStatus.setLatC(point.getY());

                /**用户码、中控码*/
                machineStatus.setUserCode(dataService.getMachine(machineStatus.getMachineId()).getUserCode());
                machineStatus.setMachineNO(dataService.getMachine(machineStatus.getMachineId()).getUserCode());
            } else {
                throw new BaseException("Machine.notActive");
            }
            Map<String, Object> map = new HashMap<>();
            map.put("machineStatuses", machineStatuses);
            map.put("workOrderFinishing", workOrderFinishMap.get(machineStatus.getMachineId()));
            mapList.add(map);
        }


        return JsonResult.succ(mapList);
    }

    /**
     * 查看工单
     *
     * @param token
     * @param workOrderId
     * @return
     */
    @RequestMapping("/getByWorkOrderId")
    public JsonResult getByWorkOrderId(String token, String workOrderId) {
        Assert.notNull(workOrderId, "WorkOrder.workOrderId.notNull");

        WorkOrderFinishing workOrderFinishing = workOrderFinishingService.getByWorkOrderId(workOrderId);

        return JsonResult.succ(workOrderFinishing);
    }

    /**
     * 查看所有未完成工单
     *
     * @param token
     * @param accountId
     * @param mapType
     * @return
     */
    @RequestMapping("/getFinish")
    public JsonResult getFinish(String token, Integer accountId, Integer mapType) {

        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }

        AccountUser accountUser = tokenService.getAccount(token);

        List<WorkOrderFinishing> workOrderFinishingList = workOrderFinishingService.getByAccountIdUserId(accountId, accountUser, null, null, null, null);
        Map<Integer, Object> workOrderFinishMap = new HashMap<>();
        for (WorkOrderFinishing workOrderFinishing : workOrderFinishingList) {
            workOrderFinishMap.put(workOrderFinishing.getMachineId(), workOrderFinishing);
        }

        List<Integer> machineIds = workOrderFinishingList.stream().map(WorkOrderFinishing::getMachineId).collect(Collectors.toList());

        List<MachineStatus> machineStatuses = machineStatusService.getByMachineIdBatch(machineIds);

        List<Map<String, Object>> map = new ArrayList<>();
        for (MachineStatus machineStatus : machineStatuses) {
            /**校准经纬度*/
            if (machineStatus != null) {
                Point point = new Point(machineStatus.getLon(), machineStatus.getLat());
                calibrateService.commonCalibrate(point, MapConstant.MAP_ORI, mapType);
                machineStatus.setLonC(point.getX());
                machineStatus.setLatC(point.getY());

                /**用户码、中控码*/
                machineStatus.setUserCode(dataService.getMachine(machineStatus.getMachineId()).getUserCode());
                machineStatus.setMachineNO(dataService.getMachine(machineStatus.getMachineId()).getUserCode());
            } else {
                throw new BaseException("Machine.notActive");
            }
            Map<String, Object> mapState = new HashMap<>();
            mapState.put("machineStatus", machineStatus);
            mapState.put("workOrderFinishing", workOrderFinishMap.get(machineStatus.getMachineId()));
            map.add(mapState);
        }

        return JsonResult.succ(map);
    }

    /**
     * 获取我的待办工单列表
     *
     * @param reqVO 待办工单查询 ReqVO
     * @return 待办工单列表
     */
    @RequestMapping("/getWorkOrderFinishingList")
    public JsonResult<WorkOrderFinishingRespVO> getWorkOrderFinishingList(WorkOrderFinishingQueryReqVO reqVO) {
        Assert.notNull(reqVO.getAccountId(), "AccountUser.agentId.notNull");
        // 设置人员编号
        AccountUser accountUser = tokenService.getAccount(reqVO.getToken());
        reqVO.setAccountUserId(accountUser.getAccountUserId());

        // 获得代办工单
        List<WorkOrderFinishing> workOrderFinishingList = workOrderFinishingService.getWorkOrderFinishingList(reqVO);

        // 查询设备信息
        List<Integer> machineIds = workOrderFinishingList.stream().map(WorkOrderFinishing::getMachineId).collect(Collectors.toList());
        Map<Integer, MachineStatus> machineStatuses = machineStatusService.getByMachineIdBatch(machineIds)
                .stream().collect(Collectors.toMap(MachineStatus::getMachineId, Function.identity()));

        List<WorkOrderFinishingRespVO.WorkOrderFinishingMachine> workOrderFinishingMachineList = new ArrayList<>();
        workOrderFinishingList.forEach(workOrderFinishing -> {

            MachineStatus machineStatus = machineStatuses.get(workOrderFinishing.getMachineId());

            if (Objects.nonNull(machineStatus)) {
                // 校准经纬度
                Point point = new Point(machineStatus.getLon(), machineStatus.getLat());
                calibrateService.commonCalibrate(point, MapConstant.MAP_ORI, reqVO.getMapType());
                machineStatus.setLonC(point.getX());
                machineStatus.setLatC(point.getY());

                // 用户码、中控码
                machineStatus.setUserCode(dataService.getMachine(machineStatus.getMachineId()).getUserCode());
                machineStatus.setMachineNO(dataService.getMachine(machineStatus.getMachineId()).getUserCode());
            }

            // 判断换电区间
            // 1. 换电判断关闭
            // 2. 车辆电量 >= 起始电量
            // 3. 结束电量不为空
            // 4. 车辆电量 <= 结束电量
            // 以上条件满足则展示
            boolean show = reqVO.getPowerSwitch().equals(0) || machineStatus.getSocPercent() >= reqVO.getStartSoc() && (reqVO.getEndSoc() == null || machineStatus.getSocPercent() <= reqVO.getEndSoc());

            if (show) {
                workOrderFinishingMachineList.add(new WorkOrderFinishingRespVO.WorkOrderFinishingMachine(machineStatus, workOrderFinishing));
            }
        });

        // 分组待办工单数量
        WorkOrderFinishingCountRespVO workOrderFinishingCount = workOrderFinishingService.getWorkOrderFinishingCount(new WorkOrderFinishingCountRespVO(), workOrderFinishingList);

        // 收集返回
        return JsonResult.succ(new WorkOrderFinishingRespVO(workOrderFinishingCount, workOrderFinishingMachineList));
    }
}
